﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.InfoCard
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Xml;
using System.Xml.Serialization;

namespace Microsoft.InfoCards
{
  internal class InfoCard : IXmlSerializable
  {
    private DateTime m_expiresOn = DateTime.MaxValue;
    private DateTime m_issuedOn = DateTime.MinValue;
    private DateTime m_installedOn = DateTime.Now;
    private string m_issuerName = string.Empty;
    private string m_language = string.Empty;
    private string m_mimeType = string.Empty;
    private string m_name = string.Empty;
    private DateTime m_lastUpdate = DateTime.MinValue;
    private string m_privacyPolicyLink = string.Empty;
    private string m_pin = string.Empty;
    private string m_oldPin = string.Empty;
    private const int InvalidRow = 0;
    private const byte Marker = 29;
    private const byte Version = 1;
    public const int KeySize = 2048;
    public const int MasterKeySize = 32;
    public const int SaltSize = 16;
    private InfoCardClaimCollection m_claims;
    private uint m_epoch;
    private Uri m_id;
    private bool m_isImported;
    private LedgerEntryCollection m_ledger;
    private byte[] m_logo;
    private int m_rowId;
    private StoreConnection m_storeConnection;
    private int m_backgroundColor;
    private string[] m_tokenTypes;
    private RequireAppliesToStatus m_requireAppliesTo;
    private byte[] m_pinHash;
    private bool m_isSelfIssued;
    private byte[] m_salt;
    private InfoCardMasterKey m_masterKey;
    private byte[] m_issuerIdentifierAsBytes;
    private Uri m_issuer;
    private uint m_privacyPolicyVersion;
    private InfoCard.PinAction m_pinAction;
    private InfocardExtendedInformationCollection m_extendedInformation;
    private bool m_readIssuerInformation;
    private RPIdentityRequirement m_rpStrongIdentityRequired;
    private List<TokenCreationParameter> m_creationParameters;

    public InfoCard()
    {
      this.m_lastUpdate = DateTime.UtcNow;
    }

    public InfoCard(Uri id)
    {
      this.m_id = id;
    }

    public InfoCard(Stream stream)
    {
      this.Deserialize(stream);
    }

    public string[] TokenTypes
    {
      set
      {
        this.m_tokenTypes = value;
      }
    }

    public List<TokenCreationParameter> CreationParameters
    {
      get
      {
        if (this.m_creationParameters == null)
          this.m_creationParameters = new List<TokenCreationParameter>();
        return this.m_creationParameters;
      }
    }

    public InfoCardClaimCollection GetClaims()
    {
      if (this.m_claims == null)
      {
        if ((Uri) null == this.m_id)
          InfoCardTrace.Assert((Uri) null != this.m_id, "m_id");
        this.m_claims = new InfoCardClaimCollection(this.m_id);
        if (this.m_storeConnection != null)
          this.m_claims.Get(this.m_storeConnection);
      }
      return this.m_claims;
    }

    public static IssuerInformation GetIssuerInformation(string xml)
    {
      IssuerInformation issuerInformation = new IssuerInformation();
      if (!string.IsNullOrEmpty(xml))
      {
        try
        {
          issuerInformation.ReadIssuerInformation(InfoCardSchemas.CreateReader(xml));
        }
        catch (Exception ex)
        {
          if (!InfoCardTrace.IsFatal(ex))
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("ServiceUnableToDeserializeInfoCardStream"), ex));
          throw;
        }
      }
      return issuerInformation;
    }

    public InfocardExtendedInformationCollection GetExtendedInformation()
    {
      if (this.m_extendedInformation == null)
      {
        InfoCardTrace.Assert((Uri) null != this.m_id, "m_id");
        this.m_extendedInformation = new InfocardExtendedInformationCollection(this.m_id);
        if (this.m_storeConnection != null)
          this.m_extendedInformation.Get(this.m_storeConnection);
      }
      return this.m_extendedInformation;
    }

    public RPIdentityRequirement GetRPIdentityRequirement()
    {
      if (this.m_rpStrongIdentityRequired == null)
      {
        this.m_rpStrongIdentityRequired = new RPIdentityRequirement(this.m_id, false);
        if (this.m_storeConnection != null)
          this.m_rpStrongIdentityRequired.Get(this.m_storeConnection);
      }
      return this.m_rpStrongIdentityRequired;
    }

    public void AddClaim(InfoCardClaim claim)
    {
      InfoCardTrace.Assert(null != claim, "null claim");
      this.GetClaims().Add(claim);
    }

    public void AddLedgerEntry(LedgerEntry entry)
    {
      InfoCardTrace.Assert(null != entry, "null ledger entry");
      this.GetLedger().Add(entry);
    }

    public DateTime ExpiresOn
    {
      get
      {
        return this.m_expiresOn;
      }
      set
      {
        this.m_expiresOn = value;
      }
    }

    public uint Epoch
    {
      get
      {
        return this.m_epoch;
      }
      set
      {
        this.m_epoch = value;
      }
    }

    public Uri Id
    {
      get
      {
        return this.m_id;
      }
      set
      {
        this.m_id = value;
      }
    }

    public DateTime IssuedOn
    {
      get
      {
        return this.m_issuedOn;
      }
      set
      {
        this.m_issuedOn = value;
      }
    }

    public string IssuerName
    {
      get
      {
        return this.m_issuerName;
      }
      set
      {
        this.m_issuerName = value;
      }
    }

    public byte[] IssuerIdentifierAsBytes
    {
      get
      {
        return this.m_issuerIdentifierAsBytes;
      }
      set
      {
        this.m_issuerIdentifierAsBytes = value;
      }
    }

    public Uri Issuer
    {
      set
      {
        this.m_issuer = value;
      }
    }

    public string Language
    {
      get
      {
        return this.m_language;
      }
      set
      {
        this.m_language = value;
      }
    }

    public RequireAppliesToStatus RequireAppliesto
    {
      get
      {
        return this.m_requireAppliesTo;
      }
      set
      {
        this.m_requireAppliesTo = value;
      }
    }

    public bool IsSelfIssued
    {
      get
      {
        return this.m_isSelfIssued;
      }
      set
      {
        this.m_isSelfIssued = value;
      }
    }

    public string PrivacyPolicyLink
    {
      get
      {
        return this.m_privacyPolicyLink;
      }
      set
      {
        this.m_privacyPolicyLink = value;
      }
    }

    public uint PrivacyPolicyVersion
    {
      get
      {
        return this.m_privacyPolicyVersion;
      }
    }

    public LedgerEntryCollection GetLedger()
    {
      if (this.m_ledger == null)
      {
        InfoCardTrace.Assert((Uri) null != this.m_id, "m_id is null");
        this.m_ledger = new LedgerEntryCollection(this.m_id);
        if (this.m_storeConnection != null)
          this.m_ledger.Get(this.m_storeConnection);
      }
      return this.m_ledger;
    }

    public StoreConnection Connection
    {
      set
      {
        this.m_storeConnection = value;
      }
    }

    public LedgerEntry TryGetLedgerEntry(
      StoreConnection connection,
      string recipientIdentifier)
    {
      LedgerEntry ledgerEntry = (LedgerEntry) null;
      InfoCardTrace.Assert(null != connection, "The store connection cannot be null.");
      InfoCardTrace.Assert(!string.IsNullOrEmpty(recipientIdentifier), "A recipient identifier must be specified.");
      if (this.m_ledger != null && this.m_ledger.ContainsKey(recipientIdentifier))
        ledgerEntry = this.m_ledger[recipientIdentifier];
      if (ledgerEntry == null)
      {
        DataRow singleRow = connection.GetSingleRow(new QueryParameter("ix_objecttype", new object[1]
        {
          (object) -1
        }), new QueryParameter("ix_parentid", new object[1]
        {
          (object) GlobalId.DeriveFrom(this.m_id.ToString())
        }), new QueryParameter("ix_name", new object[1]
        {
          (object) recipientIdentifier
        }));
        if (singleRow != null)
          ledgerEntry = new LedgerEntry((Stream) new MemoryStream(singleRow.GetDataField()), connection);
      }
      return ledgerEntry;
    }

    public LedgerEntry CreateLedgerEntry(
      Recipient recipient,
      string immediateTokenRecipientOrganizationIdentifier)
    {
      InfoCardTrace.Assert(null != recipient, "A recipient must be specified.");
      if (this.m_ledger == null)
      {
        InfoCardTrace.Assert((Uri) null != this.m_id, "The card identifier must be defined.");
        this.m_ledger = new LedgerEntryCollection(this.Id);
      }
      LedgerEntry entry = LedgerEntry.NewLedgerEntry(this.Id, recipient, this.Key, immediateTokenRecipientOrganizationIdentifier);
      this.m_ledger.Add(entry);
      return entry;
    }

    public void CheckAndUpdateLedgerEntry(LedgerEntry entry, string immediateTokenRecipientOrgId)
    {
      if (!entry.CheckAndUpdateSubjectKey(immediateTokenRecipientOrgId, this.Key))
        return;
      if (this.m_ledger == null)
      {
        InfoCardTrace.Assert((Uri) null != this.Id, "The card identifier must be defined.");
        this.m_ledger = new LedgerEntryCollection(this.Id);
      }
      if (this.m_ledger.ContainsKey(entry.Recipient.RecipientId))
        this.m_ledger[entry.Recipient.RecipientId] = entry;
      else
        this.m_ledger.Add(entry);
    }

    public byte[] Logo
    {
      get
      {
        return this.m_logo;
      }
      set
      {
        this.m_logo = value;
      }
    }

    public string LogoMimeType
    {
      get
      {
        return this.m_mimeType;
      }
      set
      {
        this.m_mimeType = value;
      }
    }

    public string Name
    {
      get
      {
        return this.m_name;
      }
      set
      {
        this.m_name = value;
      }
    }

    public DateTime LastUpdate
    {
      get
      {
        return this.m_lastUpdate;
      }
      set
      {
        this.m_lastUpdate = value;
      }
    }

    public int BackgroundColor
    {
      get
      {
        return this.m_backgroundColor;
      }
      set
      {
        this.m_backgroundColor = value;
      }
    }

    public byte[] HashSalt
    {
      set
      {
        this.m_salt = value;
      }
      get
      {
        return this.m_salt;
      }
    }

    public string[] SupportedClaimTypes
    {
      get
      {
        List<string> stringList = new List<string>();
        foreach (string key in this.GetClaims().Keys)
        {
          if (!this.IsSelfIssued || !string.IsNullOrEmpty(this.GetClaims()[key].Value))
            stringList.Add(key);
        }
        return stringList.ToArray();
      }
    }

    public bool IsImported
    {
      set
      {
        this.m_isImported = value;
      }
    }

    public DateTime InstalledOn
    {
      set
      {
        this.m_installedOn = value;
      }
    }

    public bool IsPinProtected
    {
      get
      {
        if (this.m_pinHash != null)
          return this.m_pinHash.Length > 0;
        return false;
      }
    }

    public string Pin
    {
      get
      {
        return this.m_pin;
      }
    }

    public InfoCardMasterKey GetMasterKey(StoreConnection connection)
    {
      InfoCardTrace.Assert(null != connection, "Store connection should not be null");
      this.m_masterKey = new InfoCardMasterKey(this.m_id);
      this.m_masterKey.Get(connection);
      return this.m_masterKey;
    }

    public void Decrypt()
    {
      InfoCardTrace.Assert(null != this.m_masterKey, "The GetMasterKey must be called before using this method.");
      PinProtectionHelper pinHelper = this.m_masterKey.GetPinHelper(this.m_pin);
      this.m_masterKey.Decrypt(pinHelper);
      this.GetClaims().Decrypt(pinHelper);
    }

    public byte[] Key
    {
      get
      {
        if (this.m_masterKey != null)
          return this.m_masterKey.Key;
        return (byte[]) null;
      }
    }

    public void ClearSensitiveData()
    {
      if (this.m_masterKey == null)
        return;
      Array.Clear((Array) this.m_masterKey.Key, 0, this.m_masterKey.Key.Length);
    }

    public static byte[] GenerateSalt()
    {
      byte[] data = new byte[16];
      new RNGCryptoServiceProvider().GetBytes(data);
      return data;
    }

    public void ThrowIfNotComplete()
    {
      if (!this.IsComplete())
        throw InfoCardTrace.ThrowHelperError((Exception) new SerializationIncompleteException(this.GetType()));
    }

    public bool IsComplete()
    {
      bool flag = !string.IsNullOrEmpty(this.m_language) && (Uri) null != this.m_id && ((Uri) null != this.m_issuer && !Utility.ArrayIsNullOrEmpty((Array) this.m_tokenTypes)) && (this.m_privacyPolicyLink != null && !Utility.ArrayIsNullOrEmpty((Array) this.m_salt) && (this.m_epoch > 0U && DateTime.MinValue != this.m_issuedOn)) && DateTime.MinValue != this.m_expiresOn && DateTime.MinValue != this.m_lastUpdate;
      if (!this.IsSelfIssued)
        flag = flag && this.CreationParameters.Count > 0 && null != this.m_issuerIdentifierAsBytes;
      return flag;
    }

    private RSACryptoServiceProvider GetPrivateKeyPairRsaProvider(
      string recipientIdentifier)
    {
      LedgerEntry ledgerEntry = this.TryGetLedgerEntry(this.m_storeConnection, recipientIdentifier);
      InfoCardTrace.Assert(null != ledgerEntry, "null ledger");
      RSACryptoServiceProvider cryptoServiceProvider = new RSACryptoServiceProvider(2048);
      cryptoServiceProvider.ImportCspBlob(ledgerEntry.SubjectKey);
      return cryptoServiceProvider;
    }

    public RSACryptoServiceProvider GetPrivateCryptography(
      string recipientIdentifier)
    {
      return this.GetPrivateKeyPairRsaProvider(recipientIdentifier);
    }

    public RSACryptoServiceProvider GetPublicCryptography(
      string recipientIdentifier)
    {
      RSACryptoServiceProvider keyPairRsaProvider = this.GetPrivateKeyPairRsaProvider(recipientIdentifier);
      keyPairRsaProvider.ImportCspBlob(keyPairRsaProvider.ExportCspBlob(false));
      InfoCardTrace.Assert(keyPairRsaProvider.PublicOnly, "GetPublicCryptography returns a public only rsa");
      return keyPairRsaProvider;
    }

    private void Serialize(Stream stream)
    {
      this.ThrowIfNotComplete();
      BinaryWriter writer = new BinaryWriter(stream, Encoding.Unicode);
      writer.Write((byte) 1);
      writer.Write(this.m_expiresOn.ToFileTimeUtc());
      writer.Write(this.m_epoch);
      Utility.SerializeUri(writer, this.m_id);
      writer.Write(this.m_issuedOn.ToFileTimeUtc());
      writer.Write(this.m_isImported);
      writer.Write(this.m_installedOn.ToFileTimeUtc());
      writer.Write(this.m_isSelfIssued);
      Utility.SerializeUri(writer, this.m_issuer);
      Utility.SerializeString(writer, this.m_issuerName);
      Utility.SerializeBytes(writer, this.m_issuerIdentifierAsBytes);
      Utility.SerializeString(writer, this.m_language);
      Utility.SerializeBytes(writer, this.m_logo);
      Utility.SerializeString(writer, this.m_mimeType);
      Utility.SerializeString(writer, this.m_name);
      writer.Write(this.m_lastUpdate.ToFileTimeUtc());
      writer.Write(this.m_backgroundColor);
      writer.Write((byte) this.m_requireAppliesTo);
      Utility.SerializeString(writer, this.m_privacyPolicyLink);
      writer.Write(this.m_privacyPolicyVersion);
      Utility.SerializeBytes(writer, this.m_pinHash);
      Utility.SerializeBytes(writer, this.m_salt);
      writer.Write(this.m_tokenTypes.Length);
      for (int index = 0; index < this.m_tokenTypes.Length; ++index)
        Utility.SerializeString(writer, this.m_tokenTypes[index]);
      writer.Write(this.m_creationParameters == null ? 0 : this.m_creationParameters.Count);
      if (this.m_creationParameters != null)
      {
        for (int index = 0; index < this.m_creationParameters.Count; ++index)
          this.m_creationParameters[index].Serialize(writer);
      }
      Utility.SerializeString(writer, string.Empty);
      Utility.SerializeString(writer, string.Empty);
      writer.Write((byte) this.m_pinAction);
      writer.Write((byte) 29);
    }

    public void AgentSerialize(
      Stream stream,
      bool initCalcAttributesForGetToken,
      InfoCardPolicy policy,
      StoreConnection storeConnection,
      CultureInfo userCulture)
    {
      this.Serialize(stream);
      this.m_storeConnection = storeConnection;
      this.GetRPIdentityRequirement().Serialize(stream);
      this.GetExtendedInformation().Serialize(stream);
      InfoCard.GetIssuerInformation(this.GetExtendedInformation().GetIssuerInformationElement()).Serialize(stream);
      InfoCardClaimCollection claims = this.GetClaims();
      if (policy != null && this.IsSelfIssued)
      {
        CultureInfo currentUiCulture = Thread.CurrentThread.CurrentUICulture;
        try
        {
          Thread.CurrentThread.CurrentUICulture = userCulture;
          string ppid = Utility.CreatePpid(Convert.FromBase64String(policy.ImmediateTokenRecipient.GetOrganizationPPIDIdentifier()), this.m_id);
          claims.Add(new InfoCardClaim(InfoCardConstants.PPIDClaimsUri, ppid, InfoCardConstants.ClaimsDescription(InfoCardConstants.PPID), InfoCardConstants.ClaimDisplayTag(InfoCardConstants.PPID)));
        }
        finally
        {
          Thread.CurrentThread.CurrentUICulture = currentUiCulture;
        }
      }
      claims.AgentSerialize(stream);
      BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.Unicode);
      if (initCalcAttributesForGetToken)
      {
        binaryWriter.Write(this.DoesCardMatchPolicySet(policy));
        binaryWriter.Write(this.CardMatchesPolicyRequiredIssuer(policy));
        binaryWriter.Write(this.HasCardBeenUsedBefore(policy.Recipient.GetIdentifier(), storeConnection));
        binaryWriter.Write(this.HaveRequestedClaimsChanged(policy, storeConnection));
        binaryWriter.Write(this.WillSendAppliesToInRst(policy));
        binaryWriter.Write(this.DoesCardSupportAnyOptionalClaims(policy));
        binaryWriter.Write(this.DoesCardMatchNonClaimPolicyRequirements(policy));
      }
      else
      {
        binaryWriter.Write(false);
        binaryWriter.Write(false);
        binaryWriter.Write(false);
        binaryWriter.Write(false);
        binaryWriter.Write(false);
        binaryWriter.Write(false);
        binaryWriter.Write(false);
      }
      binaryWriter.Flush();
    }

    public void CopyMetaData(InfoCard card)
    {
      this.m_salt = new byte[card.HashSalt.Length];
      Array.Copy((Array) card.HashSalt, 0, (Array) this.m_salt, 0, card.HashSalt.Length);
      this.m_pinHash = new byte[card.m_pinHash.Length];
      Array.Copy((Array) card.m_pinHash, 0, (Array) this.m_pinHash, 0, card.m_pinHash.Length);
    }

    private bool DoesCardSupportAnyOptionalClaims(InfoCardPolicy policy)
    {
      List<string> stringList = new List<string>((IEnumerable<string>) policy.OptionalClaims);
      foreach (string key in this.GetClaims().Keys)
      {
        if (stringList.Contains(key))
          return true;
      }
      return false;
    }

    private bool WillSendAppliesToInRst(InfoCardPolicy policy)
    {
      AppliesToBehaviorDecision decisionForPolicyMatch = AppliesToBehaviorDecisionTable.GetAppliesToBehaviorDecisionForPolicyMatch(policy, this.RequireAppliesto);
      return AppliesToBehaviorDecision.SendCustomAppliesTo == decisionForPolicyMatch || AppliesToBehaviorDecision.SendRPAppliesTo == decisionForPolicyMatch;
    }

    private void Deserialize(Stream stream)
    {
      BinaryReader reader = (BinaryReader) new InfoCardBinaryReader(stream, Encoding.Unicode);
      if ((byte) 1 != reader.ReadByte())
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException("ServiceCardWrongVersion"));
      this.m_expiresOn = DateTime.FromFileTimeUtc(reader.ReadInt64());
      this.m_epoch = reader.ReadUInt32();
      this.m_id = new Uri(Utility.DeserializeString(reader));
      this.m_issuedOn = DateTime.FromFileTimeUtc(reader.ReadInt64());
      this.m_isImported = reader.ReadBoolean();
      this.m_installedOn = DateTime.FromFileTimeUtc(reader.ReadInt64());
      this.m_isSelfIssued = reader.ReadBoolean();
      this.m_issuer = Utility.DeserializeUri(reader);
      this.m_issuerName = Utility.DeserializeString(reader);
      int count1 = reader.ReadInt32();
      this.m_issuerIdentifierAsBytes = reader.ReadBytes(count1);
      this.m_language = Utility.DeserializeString(reader);
      int count2 = reader.ReadInt32();
      InfoCardTrace.Assert((0 > count2 ? 0 : (count2 < 1048576 ? 1 : 0)) != 0, "logo length out of range {0}", (object) count2);
      this.m_logo = reader.ReadBytes(count2);
      this.m_mimeType = Utility.DeserializeString(reader);
      this.m_name = Utility.DeserializeString(reader);
      this.m_lastUpdate = DateTime.FromFileTimeUtc(reader.ReadInt64());
      this.m_backgroundColor = reader.ReadInt32();
      this.m_requireAppliesTo = (RequireAppliesToStatus) reader.ReadByte();
      this.m_privacyPolicyLink = Utility.DeserializeString(reader);
      this.m_privacyPolicyVersion = reader.ReadUInt32();
      int count3 = reader.ReadInt32();
      InfoCardTrace.Assert((0 > count3 ? 0 : (count3 < 1024 ? 1 : 0)) != 0, "pin hash out fo range {0}", (object) count3);
      this.m_pinHash = reader.ReadBytes(count3);
      int count4 = reader.ReadInt32();
      InfoCardTrace.Assert((0 > count4 ? 0 : (count4 < 1024 ? 1 : 0)) != 0, "salt length out of range {0}", (object) count4);
      this.m_salt = reader.ReadBytes(count4);
      int length = reader.ReadInt32();
      InfoCardTrace.Assert(32 > length, "too many token types");
      this.m_tokenTypes = new string[length];
      for (int index = 0; index < length; ++index)
        this.m_tokenTypes[index] = Utility.DeserializeString(reader);
      int num = reader.ReadInt32();
      InfoCardTrace.Assert((0 > num ? 0 : (num < 128 ? 1 : 0)) != 0, "creation parametes out of range {0}", (object) num);
      for (int index = 0; index < num; ++index)
      {
        TokenCreationParameter creationParameter = new TokenCreationParameter();
        creationParameter.Deserialize(reader);
        this.CreationParameters.Add(creationParameter);
      }
      this.m_pin = Utility.DeserializeString(reader);
      this.m_oldPin = Utility.DeserializeString(reader);
      this.m_pinAction = (InfoCard.PinAction) reader.ReadByte();
      if ((byte) 29 != reader.ReadByte())
        InfoCardTrace.Assert(false, "malformed stream detected");
      this.ThrowIfNotComplete();
    }

    public Dictionary<string, bool> GetClaimsToBeDisclosed(
      InfoCardPolicy policy,
      bool discloseOptional)
    {
      Dictionary<string, bool> dictionary = new Dictionary<string, bool>(policy.RequiredClaims.Length);
      for (int index = 0; index < policy.RequiredClaims.Length; ++index)
        dictionary.Add(policy.RequiredClaims[index], false);
      if (discloseOptional)
      {
        for (int index = 0; index < policy.OptionalClaims.Length; ++index)
        {
          if (this.GetClaims().ContainsKey(policy.OptionalClaims[index]))
            dictionary.Add(policy.OptionalClaims[index], true);
        }
      }
      return dictionary;
    }

    public bool DoesCardMatchPolicySet(InfoCardPolicy policy)
    {
      InfoCardTrace.Assert(null != policy, "null policy");
      bool flag = true;
      List<string> stringList = new List<string>((IEnumerable<string>) this.SupportedClaimTypes);
      if (policy.RequiredClaims != null)
      {
        foreach (string requiredClaim in policy.RequiredClaims)
        {
          if (!stringList.Contains(requiredClaim) && (!this.IsSelfIssued || !(InfoCardConstants.PPIDClaimsUri == requiredClaim)))
          {
            flag = false;
            break;
          }
        }
      }
      if (flag)
        return this.DoesCardMatchNonClaimPolicyRequirements(policy);
      return false;
    }

    public bool DoesCardMatchNonClaimPolicyRequirements(InfoCardPolicy policy)
    {
      InfoCardTrace.Assert(null != policy, "null policy");
      bool flag1 = true;
      if (!this.IsSelfIssued && AppliesToBehaviorDecision.FailMatch == AppliesToBehaviorDecisionTable.GetAppliesToBehaviorDecisionForPolicyMatch(policy, this.RequireAppliesto))
        flag1 = false;
      bool flag2 = true;
      if (this.GetRPIdentityRequirement().StrongIdentityRequired && !(policy.ImmediateTokenRecipient is X509RecipientIdentity))
        flag2 = false;
      if ((!this.IsSelfIssued || !policy.RequiresManagedCard) && (this.CardMatchesPolicyTokenType(policy) && this.CardMatchesPolicyRequiredIssuer(policy)) && flag1)
        return flag2;
      return false;
    }

    public bool HaveRequestedClaimsChanged(InfoCardPolicy policy, StoreConnection connection)
    {
      InfoCardTrace.Assert((Uri) null != this.m_id, "Null id");
      InfoCardTrace.Assert(null != policy, "null policy");
      InfoCardTrace.Assert(null != connection, "null connection");
      LedgerEntry ledgerEntry = this.TryGetLedgerEntry(connection, policy.Recipient.GetIdentifier());
      if (ledgerEntry == null)
        return true;
      IList list = (IList) (ledgerEntry.DisclosedClaims ?? new string[0]);
      int num1 = 0;
      if (policy.RequiredClaims != null)
        num1 = policy.RequiredClaims.Length;
      if (num1 > list.Count)
        return true;
      bool flag = true;
      foreach (string requiredClaim in policy.RequiredClaims)
      {
        if (!list.Contains((object) requiredClaim))
        {
          flag = false;
          break;
        }
      }
      int num2 = flag ? 1 : 0;
      return !flag;
    }

    private bool CardMatchesPolicyTokenType(InfoCardPolicy policy)
    {
      if (string.IsNullOrEmpty(policy.OptionalRstParams.TokenType))
        return true;
      foreach (string tokenType in this.m_tokenTypes)
      {
        if (tokenType == policy.OptionalRstParams.TokenType)
          return true;
      }
      return false;
    }

    private bool CardMatchesPolicyRequiredIssuer(InfoCardPolicy policy)
    {
      return (EndpointAddress) null == policy.Issuer || (Uri) null == policy.Issuer.Uri || Utility.CompareUri(policy.Issuer.Uri, XmlNames.WSIdentity.AnonymousIssuerUriValue) || (this.m_isSelfIssued && Utility.CompareUri(policy.Issuer.Uri, XmlNames.WSIdentity.SelfIssuerUriValue) || !this.m_isSelfIssued && Utility.CompareUri(policy.Issuer.Uri, this.m_issuer));
    }

    public bool HasCardBeenUsedBefore(string recipientId, StoreConnection connection)
    {
      return null != connection.GetSingleRow(QueryDetails.Identifiers, new QueryParameter("ix_objecttype", new object[1]
      {
        (object) -1
      }), new QueryParameter("ix_name", new object[1]
      {
        (object) recipientId
      }), new QueryParameter("ix_parentid", new object[1]
      {
        (object) GlobalId.DeriveFrom(this.m_id.ToString())
      }));
    }

    public void Get(StoreConnection con)
    {
      InfoCardTrace.Assert((Uri) null != this.m_id, "null id");
      InfoCardTrace.Assert(null != con, "null connection");
      this.m_storeConnection = con;
      DataRow row = this.GetRow(con, QueryDetails.FullRow);
      this.Deserialize((Stream) new MemoryStream(row.GetDataField()));
      this.m_rowId = row.LocalId;
    }

    public void Save(StoreConnection con)
    {
      this.ThrowIfNotComplete();
      InfoCardTrace.Assert(null != con, "null connection");
      DataRow row = this.TryGetRow(con, QueryDetails.FullHeader);
      bool flag = false;
      if (row == null)
      {
        if (this.m_masterKey == null)
          this.m_masterKey = InfoCardMasterKey.NewMasterKey(this.m_id);
        flag = true;
        row = new DataRow();
        row.ObjectType = 1;
        row.GlobalId = GlobalId.DeriveFrom(this.m_id.ToString());
      }
      InfoCardClaimCollection cardClaimCollection = (InfoCardClaimCollection) null;
      switch (this.m_pinAction)
      {
        case InfoCard.PinAction.PinSame:
          cardClaimCollection = this.m_claims.Clone();
          this.GetMasterKey(con);
          this.m_claims.Encrypt(this.m_masterKey.GetPinHelper(this.m_pin));
          break;
        case InfoCard.PinAction.PinAdded:
          cardClaimCollection = this.m_claims.Clone();
          this.GetMasterKey(con);
          PinProtectionHelper pinHelper1 = new PinProtectionHelper(this.m_pin);
          this.m_masterKey.Encrypt(pinHelper1);
          this.m_claims.Encrypt(pinHelper1);
          flag = true;
          break;
        case InfoCard.PinAction.PinRemoved:
          this.GetMasterKey(con);
          this.m_masterKey.Decrypt(this.m_masterKey.GetPinHelper(this.m_oldPin));
          flag = true;
          break;
        case InfoCard.PinAction.PinChanged:
          cardClaimCollection = this.m_claims.Clone();
          this.GetMasterKey(con);
          this.m_masterKey.Decrypt(this.m_masterKey.GetPinHelper(this.m_oldPin));
          PinProtectionHelper pinHelper2 = new PinProtectionHelper(this.m_pin);
          this.m_masterKey.Encrypt(pinHelper2);
          this.m_claims.Encrypt(pinHelper2);
          flag = true;
          break;
      }
      if (flag)
        this.m_masterKey.Save(con);
      this.m_pinAction = this.IsPinProtected ? InfoCard.PinAction.PinSame : InfoCard.PinAction.NoPin;
      string[] strArray;
      if (this.IsSelfIssued)
      {
        strArray = new string[1]
        {
          "http://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self"
        };
      }
      else
      {
        strArray = new string[this.CreationParameters.Count];
        int num = 0;
        foreach (TokenCreationParameter creationParameter in this.CreationParameters)
          strArray[num++] = creationParameter.Epr.Uri.ToString();
      }
      row.SetIndexValue("ix_production_svc_uri", (object[]) strArray);
      InfoCardTrace.Assert(null != this.m_claims, "Must already be initialized at this point");
      row.SetIndexValue("ix_supportclaim", (object[]) this.SupportedClaimTypes);
      if (this.CreationParameters.Count > 0)
      {
        object[] objArray = new object[this.CreationParameters.Count];
        int num = 0;
        foreach (TokenCreationParameter creationParameter in this.CreationParameters)
          objArray[num++] = (object) (int) creationParameter.CredentialType;
        row.SetIndexValue("ix_supportauth", objArray);
      }
      MemoryStream memoryStream = new MemoryStream();
      this.Serialize((Stream) memoryStream);
      row.SetDataField(memoryStream.ToArray());
      con.Save(row);
      this.m_rowId = row.LocalId;
      if (this.m_extendedInformation != null)
        this.m_extendedInformation.Save(con);
      this.m_claims.Save(con, this.m_isSelfIssued);
      if (cardClaimCollection != null)
        this.m_claims = cardClaimCollection;
      this.GetRPIdentityRequirement().Save(con);
    }

    public override string ToString()
    {
      return base.ToString();
    }

    public static InfoCard NewCard(CultureInfo userCulture)
    {
      InfoCard infoCard = new InfoCard();
      infoCard.m_expiresOn = DateTime.MaxValue;
      infoCard.m_epoch = 1U;
      infoCard.m_id = new Uri("urn:uuid:" + Guid.NewGuid().ToString());
      infoCard.m_issuedOn = DateTime.UtcNow;
      infoCard.m_isImported = false;
      infoCard.m_installedOn = DateTime.UtcNow;
      infoCard.m_isSelfIssued = true;
      infoCard.m_issuerName = SR.GetString("SelfIssuedIssuerName");
      infoCard.m_issuer = XmlNames.WSIdentity.SelfIssuerUriValue;
      infoCard.m_language = userCulture.TwoLetterISOLanguageName;
      infoCard.m_logo = new byte[0];
      infoCard.m_name = (string) null;
      infoCard.m_lastUpdate = DateTime.UtcNow;
      infoCard.m_backgroundColor = 16777215;
      infoCard.m_requireAppliesTo = RequireAppliesToStatus.NotPresent;
      infoCard.m_salt = InfoCard.GenerateSalt();
      infoCard.m_tokenTypes = new string[2]
      {
        "urn:oasis:names:tc:SAML:1.0:assertion",
        "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"
      };
      CultureInfo currentUiCulture = Thread.CurrentThread.CurrentUICulture;
      try
      {
        Thread.CurrentThread.CurrentUICulture = userCulture;
        for (int index = 0; index < InfoCardConstants.SelfIssuedClaimsUris.Length; ++index)
        {
          InfoCardClaim claim = new InfoCardClaim(InfoCardConstants.SelfIssuedClaimsUris[index], (string) null, InfoCardConstants.ClaimsDescription(InfoCardConstants.SelfIssuedClaimsUris[index]), InfoCardConstants.ClaimDisplayTag(InfoCardConstants.SelfIssuedClaimsUris[index]));
          infoCard.AddClaim(claim);
        }
      }
      finally
      {
        Thread.CurrentThread.CurrentUICulture = currentUiCulture;
      }
      InfoCardTrace.Assert(null == infoCard.m_masterKey, "Card key is only populated during save");
      return infoCard;
    }

    protected DataRow GetRow(StoreConnection con, QueryDetails details)
    {
      InfoCardTrace.Assert(null != con, " null connection");
      DataRow row = this.TryGetRow(con, details);
      InfoCardTrace.Assert(null != row, "null row");
      InfoCardTrace.Assert((1 == row.ObjectType ? 1 : 0) != 0, "Attempt to deserialize an incorrect object type {0}", (object) row.ObjectType);
      return row;
    }

    protected DataRow TryGetRow(StoreConnection con, QueryDetails details)
    {
      InfoCardTrace.Assert((Uri) null != this.m_id, "null id");
      InfoCardTrace.Assert(null != con, "null connection");
      return con.GetSingleRow(details, new QueryParameter("ix_globalid", new object[1]
      {
        (object) GlobalId.DeriveFrom(this.m_id.ToString())
      }));
    }

    public void ReadXml(XmlReader reader)
    {
      if ("RoamingInformationCard" == reader.LocalName)
        this.ReadRoamingInfoCard(reader);
      else if ("InformationCard" == reader.LocalName)
        this.ReadImportedInfoCard(reader);
      else
        InfoCardTrace.Assert(false, "Invalid element found. Did schema validation fail? Found {0}", (object) reader.LocalName);
    }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
      return (System.Xml.Schema.XmlSchema) null;
    }

    public void WriteXml(XmlWriter writer)
    {
      this.ThrowIfNotComplete();
      writer.WriteStartElement("RoamingInformationCard", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteStartElement("InformationCardMetaData", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteAttributeString("lang", "http://www.w3.org/XML/1998/namespace", this.m_language);
      writer.WriteStartElement("InformationCardReference", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteStartElement("CardId", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(this.m_id.AbsoluteUri);
      writer.WriteEndElement();
      writer.WriteStartElement("CardVersion", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(this.m_epoch.ToString((IFormatProvider) CultureInfo.InvariantCulture));
      writer.WriteEndElement();
      writer.WriteEndElement();
      if (!string.IsNullOrEmpty(this.m_name))
      {
        writer.WriteStartElement("CardName", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        writer.WriteString(this.m_name);
        writer.WriteEndElement();
      }
      if (this.m_logo != null && this.m_logo.Length != 0)
      {
        writer.WriteStartElement("CardImage", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        if (!string.IsNullOrEmpty(this.m_mimeType))
          writer.WriteAttributeString("MimeType", this.m_mimeType);
        string base64String = Convert.ToBase64String(this.m_logo);
        writer.WriteString(base64String);
        writer.WriteEndElement();
      }
      writer.WriteStartElement("Issuer", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      if ((Uri) null != this.m_issuer)
        writer.WriteString(this.m_issuer.AbsoluteUri);
      writer.WriteEndElement();
      writer.WriteStartElement("TimeIssued", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(XmlConvert.ToString(this.m_issuedOn, XmlDateTimeSerializationMode.Utc));
      writer.WriteEndElement();
      writer.WriteStartElement("TimeExpires", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(XmlConvert.ToString(this.m_expiresOn, XmlDateTimeSerializationMode.Utc));
      writer.WriteEndElement();
      if (this.m_creationParameters != null)
      {
        writer.WriteStartElement("TokenServiceList", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        foreach (TokenCreationParameter creationParameter in this.m_creationParameters)
          creationParameter.WriteXml(writer);
        writer.WriteEndElement();
      }
      writer.WriteStartElement("SupportedTokenTypeList", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      foreach (string tokenType in this.m_tokenTypes)
        writer.WriteElementString("TokenType", "http://schemas.xmlsoap.org/ws/2005/02/trust", tokenType);
      writer.WriteEndElement();
      writer.WriteStartElement("SupportedClaimTypeList", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      foreach (string key in this.GetClaims().Keys)
      {
        InfoCardClaim claim = this.GetClaims()[key];
        if (!this.m_isSelfIssued || !Utility.CompareUri(claim.Id, InfoCardConstants.PPIDClaimsUri))
        {
          writer.WriteStartElement("SupportedClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity");
          writer.WriteAttributeString("Uri", claim.Id);
          if (!string.IsNullOrEmpty(claim.DisplayTag))
            writer.WriteElementString("DisplayTag", "http://schemas.xmlsoap.org/ws/2005/05/identity", claim.DisplayTag);
          if (!string.IsNullOrEmpty(claim.Description))
            writer.WriteElementString("Description", "http://schemas.xmlsoap.org/ws/2005/05/identity", claim.Description);
          writer.WriteEndElement();
        }
      }
      writer.WriteEndElement();
      if (this.m_requireAppliesTo != RequireAppliesToStatus.NotPresent)
      {
        writer.WriteStartElement("RequireAppliesTo", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        if (RequireAppliesToStatus.Optional == this.m_requireAppliesTo)
          writer.WriteAttributeString("Optional", "true");
        writer.WriteEndElement();
      }
      if (!string.IsNullOrEmpty(this.m_privacyPolicyLink))
      {
        writer.WriteStartElement("PrivacyNotice", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        if (0U < this.m_privacyPolicyVersion)
          writer.WriteAttributeString("Version", this.m_privacyPolicyVersion.ToString((IFormatProvider) CultureInfo.InvariantCulture));
        writer.WriteString(this.m_privacyPolicyLink);
        writer.WriteEndElement();
      }
      if (this.GetRPIdentityRequirement().StrongIdentityRequired)
      {
        writer.WriteStartElement("RequireStrongRecipientIdentity", "http://schemas.xmlsoap.org/ws/2007/01/identity");
        writer.WriteEndElement();
      }
      if (this.GetExtendedInformation() != null)
      {
        foreach (InfocardExtendedInformationEntry informationEntry in (List<InfocardExtendedInformationEntry>) this.m_extendedInformation)
          informationEntry.WriteXml(writer);
      }
      writer.WriteStartElement("IsSelfIssued", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(XmlConvert.ToString(this.m_isSelfIssued));
      writer.WriteEndElement();
      if (!Utility.ArrayIsNullOrEmpty((Array) this.m_pinHash))
      {
        writer.WriteStartElement("PinDigest", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        writer.WriteString(Convert.ToBase64String(this.m_pinHash));
        writer.WriteEndElement();
      }
      writer.WriteStartElement("HashSalt", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(Convert.ToBase64String(this.m_salt));
      writer.WriteEndElement();
      writer.WriteStartElement("TimeLastUpdated", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(XmlConvert.ToString(this.m_lastUpdate, XmlDateTimeSerializationMode.Utc));
      writer.WriteEndElement();
      writer.WriteStartElement("IssuerId", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      if (this.m_issuerIdentifierAsBytes != null)
        writer.WriteString(Convert.ToBase64String(this.m_issuerIdentifierAsBytes, Base64FormattingOptions.None));
      writer.WriteEndElement();
      writer.WriteStartElement("IssuerName", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      if (!string.IsNullOrEmpty(this.m_issuerName))
        writer.WriteString(this.m_issuerName);
      writer.WriteEndElement();
      writer.WriteStartElement("BackgroundColor", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(XmlConvert.ToString(this.m_backgroundColor));
      writer.WriteEndElement();
      writer.WriteEndElement();
      writer.WriteStartElement("InformationCardPrivateData", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      InfoCardTrace.Assert(null != this.m_masterKey, "Masterkey Cannot be null when trying to export a card");
      writer.WriteStartElement("MasterKey", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      writer.WriteString(Convert.ToBase64String(this.m_masterKey.Key));
      writer.WriteEndElement();
      if (this.IsSelfIssued)
      {
        writer.WriteStartElement("ClaimValueList", "http://schemas.xmlsoap.org/ws/2005/05/identity");
        foreach (string key in this.GetClaims().Keys)
        {
          InfoCardClaim claim = this.GetClaims()[key];
          if (!Utility.CompareUri(claim.Id, InfoCardConstants.PPIDClaimsUri))
          {
            writer.WriteStartElement("ClaimValue", "http://schemas.xmlsoap.org/ws/2005/05/identity");
            writer.WriteAttributeString("Uri", claim.Id);
            if (!string.IsNullOrEmpty(claim.Value))
              writer.WriteElementString("Value", "http://schemas.xmlsoap.org/ws/2005/05/identity", claim.Value);
            else
              writer.WriteElementString("Value", "http://schemas.xmlsoap.org/ws/2005/05/identity", string.Empty);
            writer.WriteEndElement();
          }
        }
        writer.WriteEndElement();
      }
      writer.WriteEndElement();
      writer.WriteEndElement();
    }

    private void ReadImportedInfoCard(XmlReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      if (!reader.IsStartElement("InformationCard", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("UnexpectedElement")));
      this.Language = reader.GetAttribute("lang", "http://www.w3.org/XML/1998/namespace");
      if (string.IsNullOrEmpty(this.Language))
        this.Language = reader.GetAttribute("lang");
      reader.ReadStartElement();
      this.ReadBaseInfoCard(reader);
      if (!this.IsSelfIssued && Utility.CompareUri(this.m_issuer, XmlNames.WSIdentity.SelfIssuerUriValue))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("SelfIssuedUriUsed")));
      if (this.m_extendedInformation != null)
        return;
      this.m_extendedInformation = new InfocardExtendedInformationCollection(this.m_id);
    }

    private void ReadRoamingInfoCard(XmlReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      if (!reader.IsStartElement("RoamingInformationCard", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("UnexpectedElement")));
      reader.ReadStartElement();
      this.Language = reader.GetAttribute("lang", "http://www.w3.org/XML/1998/namespace");
      if (string.IsNullOrEmpty(this.Language))
        this.Language = reader.GetAttribute("lang");
      this.ReadBaseInfoCard(reader);
      if (this.m_isSelfIssued && this.GetClaims().ContainsKey(InfoCardConstants.PPIDClaimsUri))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("InvalidImportFile")));
      this.ReadInfoCardPrivateData(reader);
    }

    private void ReadInfoCardPrivateData(XmlReader reader)
    {
      while (reader.Read())
      {
        switch (reader.LocalName)
        {
          case "RoamingInformationCard":
            if (XmlNodeType.EndElement == reader.NodeType)
              return;
            continue;
          case "MasterKey":
            byte[] array = Utility.ReadByteStreamFromBase64(reader).ToArray();
            if (this.IsPinProtected)
            {
              if (array == null || PinProtectionHelper.EncryptedMasterKeySize != array.Length)
                throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("InvalidImportFile")));
              this.m_masterKey = new InfoCardMasterKey(this.m_id, array);
              continue;
            }
            if (array == null || 32 != array.Length)
              throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("InvalidImportFile")));
            this.m_masterKey = new InfoCardMasterKey(this.m_id, array);
            continue;
          case "ClaimValueList":
            this.ReadClaimValues(reader);
            continue;
          default:
            continue;
        }
      }
    }

    private void ReadBaseInfoCard(XmlReader reader)
    {
      try
      {
        while (reader.Read())
        {
          if ("http://schemas.xmlsoap.org/ws/2005/05/identity" == reader.NamespaceURI && XmlNodeType.EndElement == reader.NodeType && ("InformationCard" == reader.LocalName || "InformationCardMetaData" == reader.LocalName))
          {
            reader.ReadEndElement();
            break;
          }
          if ("http://schemas.xmlsoap.org/ws/2005/05/identity" != reader.NamespaceURI && XmlNodeType.Element == reader.NodeType)
          {
            if ("http://schemas.xmlsoap.org/ws/2007/01/identity" == reader.NamespaceURI && "IssuerInformation" == reader.LocalName)
            {
              if (this.m_readIssuerInformation)
                throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("MultipleIssuerInformation")));
              InfocardExtendedInformationEntry informationEntry = new InfocardExtendedInformationEntry();
              informationEntry.ReadXml(reader);
              if (this.m_extendedInformation == null)
                this.m_extendedInformation = new InfocardExtendedInformationCollection(this.m_id);
              this.m_extendedInformation.Add(informationEntry);
              this.m_readIssuerInformation = true;
              continue;
            }
            new InfocardExtendedInformationEntry().ReadXml(reader);
          }
          if ("http://schemas.xmlsoap.org/ws/2005/05/identity" == reader.NamespaceURI && XmlNodeType.EndElement != reader.NodeType)
          {
            switch (reader.LocalName)
            {
              case "CardId":
                this.Id = new Uri(reader.ReadString().Trim());
                continue;
              case "CardVersion":
                this.Epoch = Convert.ToUInt32(reader.ReadString().Trim(), (IFormatProvider) CultureInfo.InvariantCulture);
                continue;
              case "CardImage":
                this.LogoMimeType = reader.GetAttribute("MimeType", "http://schemas.xmlsoap.org/ws/2005/05/identity");
                if (string.IsNullOrEmpty(this.LogoMimeType))
                  this.LogoMimeType = reader.GetAttribute("MimeType");
                this.Logo = Utility.ReadByteStreamFromBase64(reader).ToArray();
                continue;
              case "CardName":
                this.Name = reader.ReadString().Trim();
                continue;
              case "IssuerName":
                this.IssuerName = reader.ReadString().Trim();
                continue;
              case "Issuer":
                this.Issuer = new Uri(reader.ReadString().Trim());
                continue;
              case "TimeExpires":
                this.ExpiresOn = XmlConvert.ToDateTime(reader.ReadString().Trim(), XmlDateTimeSerializationMode.Utc);
                continue;
              case "TimeIssued":
                this.IssuedOn = XmlConvert.ToDateTime(reader.ReadString().Trim(), XmlDateTimeSerializationMode.Utc);
                continue;
              case "SupportedClaimTypeList":
                this.ReadClaims(reader);
                continue;
              case "SupportedTokenTypeList":
                this.TokenTypes = this.ReadTokenType(reader).ToArray();
                continue;
              case "RequireAppliesTo":
                string attribute = reader.GetAttribute("Optional", "http://schemas.xmlsoap.org/ws/2005/05/identity");
                if (string.IsNullOrEmpty(attribute))
                  attribute = reader.GetAttribute("Optional");
                this.RequireAppliesto = string.IsNullOrEmpty(attribute) || !("true" == attribute) && !("1" == attribute) ? RequireAppliesToStatus.Required : RequireAppliesToStatus.Optional;
                continue;
              case "TokenServiceList":
                this.ReadAuthServices(reader);
                continue;
              case "PrivacyNotice":
                this.ReadPrivacyPolicy(reader);
                continue;
              case "IsSelfIssued":
                this.IsSelfIssued = Convert.ToBoolean(reader.ReadString().Trim(), (IFormatProvider) CultureInfo.InvariantCulture);
                if (this.IsSelfIssued && this.m_readIssuerInformation)
                  throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("ExtendedInfoInSelfIssued")));
                continue;
              case "PinDigest":
                byte[] array1 = Utility.ReadByteStreamFromBase64(reader).ToArray();
                if (array1 != null && array1.Length != 0)
                {
                  this.m_pinHash = array1;
                  continue;
                }
                continue;
              case "HashSalt":
                byte[] array2 = Utility.ReadByteStreamFromBase64(reader).ToArray();
                if (array2 != null && array2.Length != 0)
                {
                  this.HashSalt = array2;
                  continue;
                }
                continue;
              case "TimeLastUpdated":
                string s = reader.ReadString().Trim();
                if (!string.IsNullOrEmpty(s))
                {
                  this.LastUpdate = XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.Utc);
                  continue;
                }
                continue;
              case "IssuerId":
                byte[] array3 = Utility.ReadByteStreamFromBase64(reader).ToArray();
                if (array3 != null && array3.Length != 0)
                {
                  this.IssuerIdentifierAsBytes = array3;
                  continue;
                }
                continue;
              case "BackgroundColor":
                this.BackgroundColor = Convert.ToInt32(reader.ReadString().Trim(), (IFormatProvider) CultureInfo.InvariantCulture);
                continue;
              default:
                continue;
            }
          }
          else if ("http://schemas.xmlsoap.org/ws/2007/01/identity" == reader.NamespaceURI && XmlNodeType.EndElement != reader.NodeType && ("RequireStrongRecipientIdentity" == reader.LocalName && "http://schemas.xmlsoap.org/ws/2007/01/identity" == reader.NamespaceURI))
            this.GetRPIdentityRequirement().StrongIdentityRequired = true;
        }
      }
      catch (UriFormatException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("InvalidUriFormat"), (Exception) ex));
      }
    }

    private void ReadPrivacyPolicy(XmlReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      if (!reader.IsStartElement("PrivacyNotice", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("UnexpectedElement")));
      string attribute = reader.GetAttribute("Version", "http://www.w3.org/XML/1998/namespace");
      if (string.IsNullOrEmpty(attribute))
        attribute = reader.GetAttribute("Version");
      if (!string.IsNullOrEmpty(attribute))
        this.m_privacyPolicyVersion = Convert.ToUInt32(attribute, (IFormatProvider) CultureInfo.InvariantCulture);
      this.m_privacyPolicyLink = reader.ReadString().Trim();
    }

    private void ReadClaimValues(XmlReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      if (!reader.IsStartElement("ClaimValueList", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("UnexpectedElement")));
      while (reader.Read() && (XmlNodeType.EndElement != reader.NodeType || !("ClaimValueList" == reader.LocalName)))
      {
        if ("http://schemas.xmlsoap.org/ws/2005/05/identity" == reader.NamespaceURI && "ClaimValue" == reader.LocalName && XmlNodeType.Element == reader.NodeType)
        {
          string attribute = reader.GetAttribute("Uri", "http://www.w3.org/XML/1998/namespace");
          if (string.IsNullOrEmpty(attribute))
            attribute = reader.GetAttribute("Uri");
          reader.Read();
          string s = reader.ReadString().Trim();
          if (!this.IsPinProtected && s.Length > (int) byte.MaxValue)
            throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("TooLongClaimValue")));
          if (!string.IsNullOrEmpty(attribute))
          {
            if (!this.m_claims.ContainsKey(attribute))
              throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("InvalidImportFile")));
            if (!string.IsNullOrEmpty(s) && !this.IsPinProtected)
            {
              if (InfoCardConstants.Gender == attribute && (!("0" == s) && !("1" == s) && !("2" == s)))
                throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("InvalidImportFile")));
              if (InfoCardConstants.DateOfBirth == attribute)
              {
                try
                {
                  XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.Utc);
                }
                catch (Exception ex)
                {
                  if (InfoCardTrace.IsFatal(ex))
                    InfoCardService.Crash(ex);
                  throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("InvalidImportFile")));
                }
              }
            }
            this.m_claims[attribute].Value = s;
          }
        }
      }
    }

    private void ReadClaims(XmlReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      if (!reader.IsStartElement("SupportedClaimTypeList", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("UnexpectedElement")));
      while (reader.Read() && (XmlNodeType.EndElement != reader.NodeType || !("SupportedClaimTypeList" == reader.LocalName)))
      {
        if ("http://schemas.xmlsoap.org/ws/2005/05/identity" == reader.NamespaceURI && "SupportedClaimType" == reader.LocalName)
        {
          InfoCardClaim claim = this.ReadSingleClaim(reader);
          if (claim != null)
            this.AddClaim(claim);
        }
      }
    }

    private InfoCardClaim ReadSingleClaim(XmlReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      if (!reader.IsStartElement("SupportedClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("UnexpectedElement")));
      string displaytag = (string) null;
      string description = (string) null;
      string str = (string) null;
      string attribute = reader.GetAttribute("Uri", "http://schemas.xmlsoap.org/ws/2005/05/identity");
      if (string.IsNullOrEmpty(attribute))
        attribute = reader.GetAttribute("Uri");
      if (reader.IsEmptyElement)
      {
        if (!string.IsNullOrEmpty(attribute))
          return new InfoCardClaim(attribute, str, description, displaytag);
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("ClaimIdNull")));
      }
      while (reader.Read())
      {
        switch (reader.LocalName)
        {
          case "SupportedClaimType":
            if (XmlNodeType.EndElement == reader.NodeType)
            {
              if (!string.IsNullOrEmpty(attribute))
                return new InfoCardClaim(attribute, str, description, displaytag);
              throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("ClaimIdNull")));
            }
            continue;
          case "Description":
            description = reader.ReadString().Trim();
            continue;
          case "DisplayTag":
            displaytag = reader.ReadString().Trim();
            continue;
          case "ClaimValue":
            if (this.IsSelfIssued)
            {
              str = reader.ReadString().Trim();
              continue;
            }
            continue;
          default:
            continue;
        }
      }
      return (InfoCardClaim) null;
    }

    private void ReadAuthServices(XmlReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      if (!reader.IsStartElement("TokenServiceList", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("UnexpectedElement")));
      if (reader.IsEmptyElement)
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("NoAuthenticationServicesInCard")));
      while (reader.Read())
      {
        switch (reader.LocalName)
        {
          case "TokenService":
            if (reader.NodeType != XmlNodeType.EndElement)
            {
              TokenCreationParameter creationParameter = new TokenCreationParameter();
              creationParameter.ReadXml(reader);
              if (!creationParameter.IsComplete())
                throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("ServiceInvalidTokenService")));
              this.CreationParameters.Add(creationParameter);
              continue;
            }
            continue;
          case "TokenServiceList":
            return;
          default:
            continue;
        }
      }
    }

    private List<string> ReadTokenType(XmlReader reader)
    {
      InfoCardTrace.Assert(null != reader, "null reader");
      if (!reader.IsStartElement("SupportedTokenTypeList", "http://schemas.xmlsoap.org/ws/2005/05/identity"))
        throw InfoCardTrace.ThrowHelperError((Exception) new InvalidCardException(SR.GetString("UnexpectedElement")));
      List<string> stringList = new List<string>();
      while (reader.Read() && (XmlNodeType.EndElement != reader.NodeType || !("SupportedTokenTypeList" == reader.LocalName)))
      {
        if ("TokenType" == reader.LocalName && "http://schemas.xmlsoap.org/ws/2005/02/trust" == reader.NamespaceURI && (XmlNodeType.EndElement != reader.NodeType && !reader.IsEmptyElement))
        {
          string str = reader.ReadString().Trim();
          if (!string.IsNullOrEmpty(str))
            stringList.Add(str);
        }
      }
      return stringList;
    }

    private enum PinAction : byte
    {
      NoPin,
      PinSame,
      PinAdded,
      PinRemoved,
      PinChanged,
    }
  }
}
